using DevExpress.Blazor;
using DevExpress.ExpressApp.Blazor.Services;
using EasyXaf.LowCode.RulesEngineEditors.UndoManagers;
using Microsoft.AspNetCore.Components;
using Microsoft.JSInterop;

namespace EasyXaf.LowCode.RulesEngineEditors;

public sealed partial class RulesEngineToolbar : IDisposable
{
    private bool MiniMapVisible { get; set; } = true;

    [Parameter]
    public double Zoom { get; set; }

    [Parameter]
    public string WorkflowEleId { get; set; }

    [Parameter]
    public IUndoManager UndoManager { get; set; }

    [Parameter]
    public IJSObjectReference RulesEngineJsModule { get; set; }

    [Parameter]
    public Action RefreshViewport { get; set; }

    [Inject]
    private IImageUrlService ImageUrlService { get; set; }

    private void Undo()
    {
        UndoManager.Undo();
        RefreshViewport.Invoke();
    }

    private void Redo()
    {
        UndoManager.Redo();
        RefreshViewport.Invoke();
    }

    private async Task BestFitAsync()
    {
        var zoom = await RulesEngineJsModule.InvokeAsync<double?>("bestFit", WorkflowEleId);
        if (zoom.HasValue)
        {
            Zoom = zoom.Value;
        }
    }

    private async Task FitToViewportAsync()
    {
        var zoom = await RulesEngineJsModule.InvokeAsync<double?>("fitToViewport", WorkflowEleId);
        if (zoom.HasValue)
        {
            Zoom = zoom.Value;
        }
    }

    private async Task Zoom100Async()
    {
        await ZoomAsync(1);
    }

    private async Task ZoomInAsync()
    {
        await ZoomAsync(Zoom + 0.1);
    }

    private async Task ZoomOutAsync()
    {
        await ZoomAsync(Zoom - 0.1);
    }

    private async Task ZoomAsync(double zoom)
    {
        zoom = Math.Min(3, zoom);
        zoom = Math.Max(0.1, zoom);
        Zoom = zoom;
        await RulesEngineJsModule.InvokeVoidAsync("zoomTo", WorkflowEleId, Zoom);
    }

    private async Task VisibleOrHideMiniMapAsync(ToolbarItemClickEventArgs e)
    {
        MiniMapVisible = !MiniMapVisible;
        await RulesEngineJsModule.InvokeVoidAsync("visibleOrHideMiniMap", WorkflowEleId, MiniMapVisible);
    }

    private void UndoManager_StateChanged(object sender, EventArgs e)
    {
        InvokeAsync(StateHasChanged);
    }

    protected override void OnInitialized()
    {
        base.OnInitialized();
        UndoManager.StateChanged += UndoManager_StateChanged;
    }

    public void SetZoom(double zoom)
    {
        Zoom = zoom;
        InvokeAsync(StateHasChanged);
    }

    public void Dispose()
    {
        UndoManager.StateChanged -= UndoManager_StateChanged;
    }
}